package lenfs.impl;

import java.io.File;

import lenfs.Server;
import lenfs.util.Export;
import lenfs.util.FileHandle;
import lenfs.util.XDR;
import lenfs.util.constants.MountingConst;
import lenfs.util.constants.NFSConst;
import lenfs.util.constants.RPCConst;

public class MountingImpl extends ServerImpl {
	public MountingImpl(final Server server) {
		super(server);
	}

	private void mountprocMount(final XDR xdrPacket, long xid) {
		XDR xdrPacketReply = null;
		long xdrLength = xdrPacket.getUInt();

		// error cases
		if (xdrLength == 0) {
			xdrPacketReply = successAnswer(xdrPacket, 0, xid,
					NFSConst.NFSERR_NOENT);
			xdrPacketReply.send();
			return;
		}

		if (xdrLength < 0) {
			voidError(xdrPacket, xid, RPCConst.GARBAGE_ARGS);
			return;
		}

		else if (xdrLength > MountingConst.MNTPATHLEN) {
			xdrPacketReply = successAnswer(xdrPacket, 0, xid,
					NFSConst.NFSERR_NAMETOOLONG);
			xdrPacketReply.send();
			return;
		}

		// normal case
		String path = xdrPacket.getString(xdrLength);
		File file = new File(path);

		if (!file.exists()) {
			xdrPacketReply = successAnswer(xdrPacket, 0, xid,
					NFSConst.NFSERR_NOENT);
			xdrPacketReply.send();
			return;
		}

		Export export = server.getExport(path, xdrPacket);

		if (export == null) {
			xdrPacketReply = successAnswer(xdrPacket, 0, xid,
					NFSConst.NFSERR_NOENT);
			xdrPacketReply.send();
			return;
		}

		FileHandle handle = server.generateFileHandle(file, export);

		xdrPacketReply = successAnswer(xdrPacket, NFSConst.FHSIZE, xid,
				NFSConst.NFS_OK);

		handle.toPacket(xdrPacketReply);
		xdrPacketReply.send();
	}

	public void checkPacket(XDR packet, long xid, long proc) {
		XDR xdrPacketReply = null;
		switch ((int) proc) {
		case MountingConst.MOUNTPROC_MNT:
			mountprocMount(packet, xid);
			break;
		case MountingConst.MOUNTPROC_NULL:
			xdrPacketReply = successAnswer(packet, 0, xid, NFSConst.NFS_OK);
			xdrPacketReply.send();
			break;
		default:
			// no mount process found
			voidError(packet, xid, RPCConst.PROC_UNAVAIL);
			break;
		}
	}

	public long getProg() {
		return 100005;
	}

	public long getVersion() {
		return 1;
	}
}
